package org.ourguy.mymoviesandshows.datamodel;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;

/**
 * Series abstract data type
 * @author bordjukov
 */
//TODO add lazy season list getting - the season list to be downloaded upon
//call of the season-related methods, not earlier.
public class Series implements Serializable, ITitle {
	
	private static final long serialVersionUID = 1L;
	/**
	 * A list of the seasons of the title
	 */
	private transient ArrayList<Season> seasons;
	
	/**
	 * Day in which the title is being aired
	 */
	private String airDay;
	
	/**
	 * Time in which the title is being aired.
	 */
	private String airTime;
	
	/**
	 * Country of origin of the title
	 */
	private String country;
	
	/**
	 * The network on which the show is aired
	 */
	private String network;
	
	/**
	 * The offset of the reminder to added to the air date of the episodes
	 */
	private long reminderOffset;
	
	/**
	 * The title of the movie
	 */
	private String title;
	
	/**
	 * The release date of the title
	 */
	private java.util.Date releaseDate;
	
	/**
	 * The URL of the title
	 */
	private URL url;
	
	/**
	 * The URL of the trailer for the movie
	 */
	private URL trailerURL;
	
	/**
	 * The runtime of the title
	 */
	private int runtime;
	
	/**
	 * The plot summary of the title
	 */
	private String plot;
	
	/**
	 * The IMDb ID of the title
	 */
	private String imdbId;
	
	/**
	 * The API-Specific ID of the title
	 */
	private String apiId;
	
	/**
	 * Cover art for the title
	 */
	private ICoverArt coverArt;
	
	/**
	 * Genre list for the title
	 */
	private String[] genre;
		
	/**
	 * Watched flag for the title
	 */
	private boolean watched;
	
	/**
	 * Favourite flag for the title
	 */
	private boolean favorite;

	/**
	 * Cast of the title
	 */
	private Cast cast;
	
	/**
	 * Title rating
	 */
	private float rating;
	
	/**
	 * Tracking list indicator.
	 */
	private boolean tracked;
	
	/**
	 * Instantiate a new series by title, plot and API-specific ID
	 * @param name
	 * @param plot
	 * @param apiId
	 */
	public Series(){
	}
	
	public Series(String apiId, String title, String plot){
		this.apiId = apiId;
		this.title = title;
		this.plot = plot;
		seasons = null;
	}
	
	/**
	 * Add a season to the list of seasons of the title
	 * @param season the season to add
	 */
	public void addSeason(Season season){
		seasons.add(season);
	}
	
	/**
	 * Remove a specific season from the list of seasons
	 * @param season the season to remove
	 */
	public void removeSeason(Season season){
		seasons.remove(season);
	}
	
	public void setSeasons(ArrayList<Season> seasons)
	{
		this.seasons = seasons;
	}
	
	/**
	 * Get the season at the given index
	 * @param index the index of the season
	 * @return the sought season
	 */
	//TODO add lazy loading for the seasons
	public Season getSeasonAt(int index){
		if (seasons != null && index < seasons.size() && index >= 0){
			return seasons.get(index);
		}
		else{
			return null;
		}
	}
	
	/**
	 * Get the number of seasons for the given title
	 * @return the number of seasons
	 */
	//TODO add lazy loading for the seasons
	public int getSeasonCount(){
		return seasons.size();
	}
	
	/**
	 * Get the seasons of the given title
	 * @return the seasons
	 */
	public ArrayList<Season> getSeasonList(){
		return seasons;
	}

	/**
	 * Get the air day of the title
	 * @return the air day
	 */
	public String getAirDay() {
		return airDay;
	}

	/**
	 * Set the air day of the title
	 * @param airDay
	 */
	public void setAirDay(String airDay) {
		this.airDay = airDay;
	}

	/**
	 * Get the air time of the title
	 * @return the air time of the title
	 */
	//TODO add time zone conversion
	//from trakt's docs:
	//Any dates returned from the API (i.e. watched timestamps) are in the
	//PST (GMT-8) timezone. Adjust accordingly on your end to your local TZ.
	public String getAirTime() {
		return airTime;
	}

	/**
	 * Set the air time of the title
	 * @param airTime the air time to set
	 */
	public void setAirTime(String airTime) {
		this.airTime = airTime;
	}
	
	/**
	 * @return the country
	 */
	public String getCountry() {
		return country;
	}

	/**
	 * @param country the country to set
	 */
	public void setCountry(String country) {
		this.country = country;
	}
	
	/**
	 * Set the external link of the title
	 * @param newLink
	 */
	public void setExternalLink(java.net.URL newLink) {
		this.url = newLink;
	}


	/**
	 * Set the URL of the trailer for the title
	 * @param url
	 */
	public void setTrailer(URL url) {
		this.trailerURL = url;
	}

	/**
	 * Re-set the title
	 * @param title the title to set
	 */
	public void setTitle(String title) {
		this.title = title;
	}
	
	public void setImdbId(String imdbId) {
		this.imdbId = imdbId;
	}

	public void setReleaseDate(Date date) {
		releaseDate = date;
	}


	public void setCast(Cast cast) {
		this.cast = cast;
	}

	public void setPlot(String plot) {
		this.plot = plot;
	}


	public void setRating(float newRating) {
		rating = newRating;
	}
	
	public void setWatched() {
		watched = true;
	}

	public void setUnWatched() {
		watched = false;
	}
	
	/**
	 * @see Movie#setExternalLink
	 */
	public void setURL(URL url) {
		setExternalLink(url);
	}
	
	public void setRuntime(int runtime) {
		this.runtime = runtime;
	}
	
	public boolean isWatched(){
		return watched;
	}

	public void addToFavorites() {
		favorite = true;
	}

	public void removeFromFavorites() {
		favorite = false;
	}
	
	public boolean isInFavorites(){
		return favorite;
	}

	public URL getExternalLink() {
		return url;
	}

	/**
	 * Get the trailer of the title
	 */
	public URL getTrailer() {
		return trailerURL;
	}

	public String getTitle() {
		return title;
	}

	public String getImdbId() {
		return imdbId;
	}

	public Date getReleaseDate() {
		return releaseDate;
	}

	public String[] getGenre() {
		return genre;
	}

	public Cast getCast() {
		return cast;
	}

	public String getPlot() {
		return plot;
	}

	public float getRating() {
		return rating;
	}

	/**
	 * Get the url of the title
	 * @return
	 * @see Movie#getExternalLink()
	 */
	public URL getURL() {
		return url;
	}

	public int getRuntime() {
		return runtime;
	}

	/**
	 * Get the cover art of the title
	 * @return
	 */
	public ICoverArt getCoverArt() {
		return coverArt;
	}

	/**
	 * Set the cover art of the title by URL
	 * @param url
	 * @throws MalformedURLException
	 */
	public void setCoverArt(String url) throws MalformedURLException {
		this.coverArt = new CoverArtFromURL(url);
	}
	
	/**
	 * Set the cover art of the title by image
	 * @param image
	 */
	public void setCoverArt(android.graphics.Bitmap image) {
		this.coverArt = new CoverArtFromImage(image);
	}

	/**
	 * Get the list of genres for the title
	 * @param genres
	 */
	public void setGenreList(String ... genres) {
		this.genre = genres;
	}
	
	public void setGenre(String[] genre) {
		this.genre = genre;
	}
	
	/**
	 * @return the apiId
	 */
	public String getApiId() {
		return apiId;
	}

	/**
	 * @param apiId the apiId to set
	 */
	public void setApiId(String apiId) {
		this.apiId = apiId;
	}
	
	/**
	 * @return the network
	 */
	public String getNetwork() {
		return network;
	}

	/**
	 * @param network the network to set
	 */
	public void setNetwork(String network) {
		this.network = network;
	}

	/**
	 * @return the reminderOffset
	 */
	public long getReminderOffset() {
		return reminderOffset;
	}

	/**
	 * @param reminderOffset the reminderOffset to set
	 */
	public void setReminderOffset(long reminderOffset) {
		this.reminderOffset = reminderOffset;
	}

	public boolean isTracked() {
		return this.tracked;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((apiId == null) ? 0 : apiId.hashCode());
		result = prime * result + ((imdbId == null) ? 0 : imdbId.hashCode());
		return result;
	}


	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Series other = (Series) obj;
		if (apiId == null) {
			if (other.apiId != null)
				return false;
		} else if (!apiId.equals(other.apiId))
			return false;
		if (imdbId == null) {
			if (other.imdbId != null)
				return false;
		} else if (!imdbId.equals(other.imdbId))
			return false;
		return true;
	}
	
	/* (non-Javadoc)
	 * @see ITitle#compareTo(ITitle)
	 */
	public int compareTo(ITitle title) {
		int result = this.title.compareTo(title.getTitle());
		if (result == 0)
			result = this.releaseDate.compareTo(title.getReleaseDate());
		return result;
	}
}
